package com.suning.sawp.service.impl.mainpushnew;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import scala.collection.mutable.StringBuilder;

import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import com.suning.sawp.constants.MainPushConstants;
import com.suning.sawp.constants.MainPushErrorConstants;
import com.suning.sawp.dto.common.QueryResult;
import com.suning.sawp.dto.common.ReturnMsg;
import com.suning.sawp.dto.precharge.CommonRtn;
import com.suning.sawp.exception.SawpException;
import com.suning.sawp.intf.dao.mainpushnew.AreaTaskDao;
import com.suning.sawp.intf.dao.mainpushnew.MainPushTaskHqHandleDao;
import com.suning.sawp.intf.dao.mainpushnew.RedPointTipsDao;
import com.suning.sawp.intf.mainpushnew.DistributeStatusService;
import com.suning.sawp.intf.mainpushnew.MainPushHqImportService;
import com.suning.sawp.intf.mainpushnew.MainPushTaskHqHandleService;
import com.suning.sawp.po.mainpushnew.AreaModelRel;
import com.suning.sawp.po.mainpushnew.AreaTask;
import com.suning.sawp.po.mainpushnew.HqTask;
import com.suning.sawp.po.mainpushnew.Model;
import com.suning.sawp.po.mainpushnew.ModelCmmdty;
import com.suning.sawp.po.mainpushnew.RedPointTips;
import com.suning.sawp.service.util.DateUtils;
import com.suning.sawp.service.util.ExcelUtils;
import com.suning.sawp.vo.mainpushnew.HqModelAllocateFormVo;
import com.suning.sawp.vo.mainpushnew.HqModelAllocateVo;
import com.suning.sawp.vo.mainpushnew.HqTaskVo;
import com.suning.sawp.vo.mainpushnew.TaskModelVo;

/**
 * 
 * 总部主推任务维护接口实现<br>
 *
 * @author 14060886 祝翔龙
 */
@Service
public class MainPushTaskHqHandleServiceImpl implements MainPushTaskHqHandleService {

	@Autowired
	private MainPushHqImportService mainPushHqImportService;
	@Autowired
	private DistributeStatusService distributeStatusService;

	@Autowired
	private MainPushTaskHqHandleDao mainPushTaskHqHandleDao;
	@Autowired
	private AreaTaskDao areaTaskDao;
	@Autowired
	private RedPointTipsDao redPointTipsDao;

	public ReturnMsg<QueryResult<HqTask>> queryPageHqTask(Map<String, Object> paramsMap) {
		int total = mainPushTaskHqHandleDao.countPageHqTask(paramsMap);
		QueryResult<HqTask> result = new QueryResult<HqTask>();
		result.setTotalSize(total);
		if (total > 0) {
			List<HqTask> list = mainPushTaskHqHandleDao.queryPageHqTask(paramsMap);
			result.setRecords(list);
		}

		ReturnMsg<QueryResult<HqTask>> returnMsg = new ReturnMsg<QueryResult<HqTask>>();
		returnMsg.setRetFlag(ReturnMsg.SUCCESS);
		returnMsg.setData(result);
		return returnMsg;
	}

	@Override
	public ReturnMsg<HqTask> queryTaskInfo(Long hqTaskId) {
		HqTaskVo hqTask = mainPushTaskHqHandleDao.selectHqTaskInfoById(hqTaskId);
		if (null == hqTask) {
			throw new SawpException("未查询到该总部任务");
		}
		hqTask.setRate(hqTask.getRate().multiply(BigDecimal.valueOf(100)));
		hqTask.setMonthFormat(DateUtils.getFormatDay(hqTask.getMonth(), DateUtils.YYYYMM_PATTERN, DateUtils.DEFAULT_MONTH_PATTERN).replace("-", "年") + "月");
		ReturnMsg<HqTask> result = new ReturnMsg<HqTask>();
		result.setRetFlag(ReturnMsg.SUCCESS);
		result.setData(hqTask);
		return result;
	}

	@Override
	public ReturnMsg<QueryResult<TaskModelVo>> queryTaskModelDetail(Long hqTaskId, Map<String, Integer> pageParams) {
		Integer count = mainPushTaskHqHandleDao.countModelInfoByTask(hqTaskId);
		List<TaskModelVo> models = mainPushTaskHqHandleDao.selectModelInfoByTask(hqTaskId, pageParams);
		if (CollectionUtils.isEmpty(models)) {
			throw new SawpException("未查询到该任务对应的款数信息");
		}
		ReturnMsg<QueryResult<TaskModelVo>> result = new ReturnMsg<QueryResult<TaskModelVo>>();
		QueryResult<TaskModelVo> pageResult = new QueryResult<TaskModelVo>();
		pageResult.setTotalSize(count);
		pageResult.setRecords(models);
		result.setRetFlag(ReturnMsg.SUCCESS);
		result.setData(pageResult);
		return result;
	}

	// 创建总部任务
	@Transactional
	public ReturnMsg<List<String>> importFirstExcel(MultipartFile file, String month) {
		// 查询当月所有的任务
		List<HqTask> hqTasks = mainPushTaskHqHandleDao.queryHqTaskByMonth(month);
		// 1：判断当月任务是否可以创建,并删除已存在的进行中任务
		if (!checkCanCreate(hqTasks)) {
			ReturnMsg<List<String>> returnMsg = new ReturnMsg<List<String>>();
			returnMsg.setError(MainPushErrorConstants.TASK_ERR_000, MainPushErrorConstants.MAIN_PUSH_ERR_MAP);
			return returnMsg;
		}
		// 2：解析导入的excel,并返回解析的结果
		ReturnMsg<List<String>> returnMsg = mainPushHqImportService.importFirstExcel(file, month);

		return returnMsg;
	}

	public ReturnMsg<List<String>> importSecondExcel(MultipartFile file, String month) {
		ReturnMsg<List<String>> returnMsg = mainPushHqImportService.importSecondExcel(file, month);
		return returnMsg;
	}

	@Override
	public ReturnMsg<CommonRtn> modityTaskRate(Long hqTaskId, String rate) {

		mainPushTaskHqHandleDao.updateTaskRateById(hqTaskId, new BigDecimal(rate).divide(new BigDecimal(100)));
		ReturnMsg<CommonRtn> result = new ReturnMsg<CommonRtn>();
		result.setRetFlag(ReturnMsg.SUCCESS);
		return result;
	}

	private boolean checkCanCreate(List<HqTask> hqTasks) {
		// 某月 未创建任务
		if (CollectionUtils.isEmpty(hqTasks)) {
			return true;
		}
		// 正在创建中的任务
		List<HqTask> creatingList = groupHqTaskByStatus(hqTasks, MainPushConstants.CREATING);
		// 已创建的任务
		List<HqTask> completeList = groupHqTaskByStatus(hqTasks, MainPushConstants.COMPLETE);
		// 这个月所有的任务都是已完成的任务，那么肯定不可以继续创建任务了
		if (completeList.size() == MainPushConstants.HQTASK_MAXNUM_PER_MONTH) {
			return false;
		}
		// 存在创建中的任务，那么全部删除
		if (creatingList.size() > 0) {
			// 删除创建中的任务
			for (HqTask task : creatingList) {
				mainPushTaskHqHandleDao.deleteHqTaskById(task.getId());
			}
		}
		return true;
	}

	/**
	 * 根据订单创建状态，分组
	 * 
	 * @param list
	 *            某月所有的任务
	 * @param status
	 *            0：创建中，1：创建完成
	 * @return
	 */
	private List<HqTask> groupHqTaskByStatus(List<HqTask> list, final Short status) {
		List<HqTask> subList = Lists.newArrayList();
		Predicate<HqTask> predicate = new Predicate<HqTask>() {
			public boolean apply(HqTask input) {
				return status.equals(input.getTaskStatus());
			}
		};
		subList = FluentIterable.from(list).filter(predicate).toList();
		return subList;
	}

	@Override
	public ReturnMsg<List<HqModelAllocateVo>> queryAreaAllocateDetail(Long hqTaskId, Long modelId) {
		List<HqModelAllocateVo> modelAllocates = mainPushTaskHqHandleDao.selectAreaAllocateDetailByModel(hqTaskId, modelId);
		if (CollectionUtils.isEmpty(modelAllocates)) {
			throw new SawpException("未查询到该任务的分配信息");
		}
		ReturnMsg<List<HqModelAllocateVo>> result = new ReturnMsg<List<HqModelAllocateVo>>();
		result.setRetFlag(ReturnMsg.SUCCESS);
		result.setData(modelAllocates);
		return result;
	}

	@Override
	@Transactional
	public ReturnMsg<CommonRtn> allocateModel(HqModelAllocateFormVo formVo) {
		List<HqModelAllocateVo> areaAllocates = formVo.getAreaAllocates();
		if (CollectionUtils.isNotEmpty(areaAllocates)) {
			Integer targetNum = NumberUtils.INTEGER_ZERO;
			Long modelId = formVo.getModelId();
			for (HqModelAllocateVo item : areaAllocates) {
				if (null != item.getAreaTaskId()) {
					item.setModelId(formVo.getModelId());
					item.setTargetNum(null == item.getTargetNum() ? NumberUtils.INTEGER_ZERO : item.getTargetNum());
					// 更新目标台数
					mainPushTaskHqHandleDao.updateModelTargetByArea(item);
					// 更新分配状态
					distributeStatusService.modifyAreaTaskStatus4ModifyModelNum(item.getAreaTaskId(), modelId);
				}
				// 统计总目标台数
				targetNum += item.getTargetNum();
			}
			mainPushTaskHqHandleDao.updateModelTargetByCode(modelId, formVo.getHqTaskId(), targetNum);
		}
		ReturnMsg<CommonRtn> result = new ReturnMsg<CommonRtn>();
		result.setRetFlag(ReturnMsg.SUCCESS);
		return result;
	}

	@Override
	public ReturnMsg<CommonRtn> removeModel(Long hqTaskId, Long modelId) {
		// 级联删除款数、款数商品关系、大区款数关系、门店款数关系和店员款数关系
		mainPushTaskHqHandleDao.deleteModeById(hqTaskId, modelId);
		mainPushTaskHqHandleDao.deleteModelCmmdtyRelById(hqTaskId, modelId);
		mainPushTaskHqHandleDao.deleteAreaModelRelById(hqTaskId, modelId);
		mainPushTaskHqHandleDao.deleteStoreModelRelById(hqTaskId, modelId);
		mainPushTaskHqHandleDao.deleteStaffModelRelById(hqTaskId, modelId);
		// 更新任务分配状态
		distributeStatusService.modifyAreaTaskStatus4DeleteModel(hqTaskId, modelId);
		ReturnMsg<CommonRtn> result = new ReturnMsg<CommonRtn>();
		result.setRetFlag(ReturnMsg.SUCCESS);
		return result;
	}

	/**
	 * 模板格式
	 * 
	 * [SPACE] 主推类型 A B ... [SPACE] 商品款数 款数1 款数2 ... 大区编码 商品编码 10010025,10010026
	 * 10010027,10010028 ... 10001965 南京大区 100 200 ... ... ... ... ... ...
	 * 
	 * 1、解析验证 2、保存款数信息 3、保存款数商品关系 4、保存小红点消息 5、保存大区款数关系
	 */
	@Override
	@Transactional
	public ReturnMsg<CommonRtn> addModel(Sheet sheet, Long hqTaskId) {
		ReturnMsg<CommonRtn> result = new ReturnMsg<CommonRtn>();
		StringBuilder errorMsg = new StringBuilder(); // 存放错误结果集
		// 查询总部主推任务信息
		HqTaskVo hqTask = mainPushTaskHqHandleDao.selectHqTaskInfoById(hqTaskId);
		if (null == hqTask) {
			throw new SawpException("未查询到主推任务信息");
		}

		// 按列解析款数和款数商品关系信息
		// 主推类型行A,B,B2
		Row taskTypeRow = sheet.getRow(0);
		// 款数行
		Row modelRow = sheet.getRow(1);
		// 商品编码集行
		Row cmmdtyCodesRow = sheet.getRow(2);
		// 获取总列数
		int columnLength = taskTypeRow.getLastCellNum();
		if (columnLength < 3) {
			errorMsg.append("文件至少需包含3列数据;");
		}
		Map<String, Model> modelMap = new HashMap<String, Model>(); // 存放款数信息
																	// Key是款数名称
		for (int i = 2; i < columnLength; i++) {
			String taskType = ExcelUtils.getValueFromCell(taskTypeRow.getCell(i));
			String modelName = ExcelUtils.getValueFromCell(modelRow.getCell(i));
			String cmmdtyCodes = ExcelUtils.getValueFromCell(cmmdtyCodesRow.getCell(i));
			// 验证主推类型、款数类型和商品编码
			if (modelMap.containsKey(modelName) || null != mainPushTaskHqHandleDao.hasModelaByName(hqTaskId, modelName)) {
				errorMsg.append("第2行,第" + (i + 1) + "列款数名称不能重复;");
			}
			errorMsg = checkCell(taskType, 0, i, MainPushConstants.CHECK_TYPE_TASKTYPE, errorMsg);
			errorMsg = checkCell(modelName, 1, i, MainPushConstants.CHECK_TYPE_MODELNAME, errorMsg);
			errorMsg = checkCell(cmmdtyCodes, 2, i, MainPushConstants.CHECK_TYPE_CMMDTYCODES, errorMsg);
			if (StringUtils.isBlank(errorMsg.toString())) {
				Model model = getModel(hqTask, hqTaskId, modelName, taskType);
				// 保存款数信息
				Long modelId = mainPushTaskHqHandleDao.insertModel(model);
				model.setId(modelId);
				modelMap.put(modelName, model);
				List<String> cmmdtyList = Arrays.asList(cmmdtyCodes.split(","));
				for (String cmmdtyCode : cmmdtyList) {
					if (StringUtils.isNotBlank(cmmdtyCode)) {
						// 保存款数商品关系
						mainPushTaskHqHandleDao.insertModelCmmdty(getModelCmmdty(hqTask, hqTaskId, modelName, cmmdtyCode, Long.valueOf(modelId)));
					}
				}
				// 保存小红点消息
				String thisMonth = DateUtils.getThisMonth();
				if (hqTask.getMonth().equals(thisMonth)) {
					redPointTipsDao.insertRedPointTips(getRedPointTips(Long.valueOf(modelId), thisMonth));
				}
			}
		}
		// 抛出第一步解析错误信息
		if (StringUtils.isNotBlank(errorMsg.toString())) {
			throw new SawpException(errorMsg.toString());
		}

		// 按行解析大区和大区目标台数关系信息
		List<AreaModelRel> rels = new ArrayList<AreaModelRel>();
		int rowLength = sheet.getPhysicalNumberOfRows();
		Integer areaNum = mainPushTaskHqHandleDao.countArea();
		if (rowLength != (areaNum + 3)) {
			errorMsg.append("大区信息不完整;");
		}
		Set<String> disCodeCheckSet = new HashSet<String>();
		for (int i = 3; i < rowLength; i++) {
			String disCode = ExcelUtils.getValueFromCell(sheet.getRow(i).getCell(0));
			String disName = ExcelUtils.getValueFromCell(sheet.getRow(i).getCell(1));
			if (disCodeCheckSet.contains(disCode)) {
				errorMsg.append("第" + (i + 1) + "行,第1列大区编码不能重复;");
			}
			disCodeCheckSet.add(disCode);
			// 验证大区编码和大区名称
			errorMsg = checkCell(disCode, i, 0, MainPushConstants.CHECK_TYPE_DISCODE, errorMsg);
			errorMsg = checkCell(disName, i, 1, MainPushConstants.CHECK_TYPE_DISNAME, errorMsg);
			for (int j = 2; j < columnLength; j++) {
				String targetNum = ExcelUtils.getValueFromCell(sheet.getRow(i).getCell(j));
				targetNum = defaultZero(targetNum);
				// 验证目标台数
				errorMsg = checkCell(targetNum, i, j, MainPushConstants.CHECK_TYPE_TARGETNUM, errorMsg);
				if (StringUtils.isBlank(errorMsg.toString())) {
					// 获得大区对应的款数名称
					String modelName = ExcelUtils.getValueFromCell(sheet.getRow(1).getCell(j));
					Model model = modelMap.get(modelName);
					model.setTargetNum(defaultZero(model.getTargetNum()) + Integer.valueOf(targetNum));
					modelMap.put(modelName, model);
					// 查询大区任务信息
					AreaTask areaTask = areaTaskDao.selectAreaTaskByIdAndDisCode(hqTaskId, disCode);
					if (null == areaTask) {
						throw new SawpException("请先创建大区任务");
					}
					rels.add(getAreaModelRel(hqTaskId, areaTask.getId(), model.getId(), Integer.valueOf(targetNum)));
				}
			}
		}
		// 抛出第二步解析错误信息
		if (StringUtils.isNotBlank(errorMsg.toString())) {
			throw new SawpException(errorMsg.toString());
		}
		// 批量保存大区款数关系
		mainPushTaskHqHandleDao.batchInsertAreaModelRel(rels);
		// 批量更新款数目标总数
		Collection<Model> values = modelMap.values();
		mainPushTaskHqHandleDao.batchUpdateModel(new ArrayList<Model>(values));
		// 更新分配状态
		distributeStatusService.modifyAreaTaskStatus4NewModel(hqTaskId);
		result.setRetFlag(ReturnMsg.SUCCESS);
		return result;
	}

	/**
	 * 
	 * 功能描述: 单元格内容验证<br>
	 *
	 * @param str
	 * @param i
	 * @param j
	 * @param type
	 * @return
	 */
	private StringBuilder checkCell(String str, int i, int j, Integer type, StringBuilder errorMsg) {
		switch (type) {
		case 1:
			if (StringUtils.isBlank(str)) {
				errorMsg.append("第" + (i + 1) + "行,第" + (j + 1) + "列列主推类型不能为空;");
			}
			if (!("A".equals(str) || "B".equals(str) || "B2".equals(str))) {
				errorMsg.append("第" + (i + 1) + "行,第" + (j + 1) + "列主推类型必须为A类、B类或B2类;");
			}
			break;
		case 2:
			if (StringUtils.isBlank(str)) {
				errorMsg.append("第" + (i + 1) + "行,第" + (j + 1) + "列款数名称不能为空;");
			}
			break;
		case 3:
			if (StringUtils.isBlank(str)) {
				errorMsg.append("第" + (i + 1) + "行,第" + (j + 1) + "列商品编码不能为空;");
				break;
			}
			List<String> cmmdtyList = Arrays.asList(str.split(","));
			Set<String> cmmdtyCheckSet = new HashSet<String>();
			for (String cmmdtyCode : cmmdtyList) {
				cmmdtyCode = cmmdtyCode.trim();
				if (!StringUtils.isNumeric(cmmdtyCode)) {
					errorMsg.append("第" + (i + 1) + "行,第" + (j + 1) + "列商品编码必须为数字;");
				}
				if (cmmdtyCheckSet.contains(cmmdtyCode)) {
					errorMsg.append("第" + (i + 1) + "行,第" + (j + 1) + "列商品编码不能重复;");
				}
				cmmdtyCheckSet.add(cmmdtyCode);
			}
			break;
		case 4:
			if (StringUtils.isBlank(str)) {
				errorMsg.append("第" + (i + 1) + "行,第" + (j + 1) + "列大区编码不能为空;");
			}
			if (null == mainPushTaskHqHandleDao.hasAreaByCode(str)) {
				errorMsg.append("第" + (i + 1) + "行,第" + (j + 1) + "列不存在该大区编码;");
			}
			break;
		case 5:
			if (StringUtils.isBlank(str)) {
				errorMsg.append("第" + (i + 1) + "行,第" + (j + 1) + "列大区名称不能为空;");
			}
			break;
		case 6:
			if (StringUtils.isNotBlank(str) && !StringUtils.isNumeric(str)) { // 目标台数可以是空是0
																				// 不为空时必须是数字
				errorMsg.append("第" + (i + 1) + "行,第" + (j + 1) + "列目标台数必须为数字;");
			}
			break;
		}
		return errorMsg;
	}

	private Model getModel(HqTask hqTask, Long hqTaskId, String modelName, String taskType) {
		Model model = new Model();
		model.setHqTaskId(hqTaskId);
		model.setCateCode(hqTask.getCateCode());
		model.setCateName(hqTask.getCateName());
		model.setModelName(modelName);
		model.setTaskType(taskType);
		return model;
	}

	private ModelCmmdty getModelCmmdty(HqTask hqTask, Long hqTaskId, String modelName, String cmmdtyCode, Long modelId) {
		ModelCmmdty rel = new ModelCmmdty();
		rel.setModelId(modelId);
		rel.setHqTaskId(hqTaskId);
		rel.setCateCode(hqTask.getCateCode());
		rel.setModelName(modelName);
		rel.setCmmdtyCode(cmmdtyCode);
		return rel;
	}

	private AreaModelRel getAreaModelRel(Long hqTaskId, Long areaTaskId, Long modelId, Integer targetNum) {
		AreaModelRel rel = new AreaModelRel();
		rel.setHqTaskId(hqTaskId);
		rel.setAreaTaskId(areaTaskId);
		rel.setModelId(modelId);
		rel.setTargetNum(targetNum);
		rel.setDistStatus(MainPushConstants.STORE_TASK_MODEL_STATUS_UNDISTRIBUTED);
		return rel;
	}

	private RedPointTips getRedPointTips(Long modelId, String month) {
		RedPointTips tips = new RedPointTips();
		tips.setModelId(modelId);
		tips.setMonth(month);
		tips.setCreateTime(new Date());
		tips.setStoreCode(MainPushConstants.ALL_STORE);
		tips.setChangeType(MainPushConstants.TASK_CHANGE_TYPE);
		return tips;
	}

	private String defaultZero(String value) {
		return value = StringUtils.isBlank(value) ? "0" : value;
	}

	private Integer defaultZero(Integer value) {
		return value = null == value ? NumberUtils.INTEGER_ZERO : value;
	}

	public ReturnMsg<HqTask> delHqTask(Long id) {
		mainPushTaskHqHandleDao.deleteHqTaskById(id);
		return new ReturnMsg<HqTask>();
	}
}
